package com.miaosha.controller;

import com.miaosha.annotation.AuthToken;
import com.miaosha.entity.User;
import com.miaosha.entity.UserRole;
import com.miaosha.service.UserRoleService;
import com.miaosha.service.UserService;
import com.miaosha.utils.CommonResult;
import com.miaosha.entity.dto.UserDto;
import com.miaosha.utils.JwtTokenUtil;
import com.miaosha.utils.TokenResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.TimeUnit;

@AuthToken
@RequestMapping("/user")
@RestController
@Slf4j
public class UserController {

    @Autowired
    UserService userService;

    @Autowired
    UserRoleService userRoleService;

    @Autowired
    JwtTokenUtil jwtTokenUtil;

    @Autowired
    HttpServletRequest request;

    @Autowired
    RedisTemplate<String,Object> redisTemplate;

    @Value("${jwt.access_token.expiration}")
    private Long accessTokenExpiration;

    @Value("${jwt.refresh_token.expiration}")
    private Long refreshTokenExpiration;

    @PostMapping("/refresh-token")
    public CommonResult<TokenResponse> refreshToken(@RequestBody TokenResponse tokenResponse){

        String refreshToken = tokenResponse.getRefreshToken();

        // 先判断refreshToken是否在Redis中
        Long userId = (Long) redisTemplate.opsForValue().get(refreshToken);

        if(userId==null){ // refreshToken不存在
            return  CommonResult.error(0, "Refresh token expired");
        }
        String accessToken = jwtTokenUtil.generateAccessToken(userId);
        redisTemplate.opsForValue().set(accessToken,userId,accessTokenExpiration, TimeUnit.SECONDS);
        tokenResponse.setAccessToken(accessToken);
        return CommonResult.success(tokenResponse);
    }

    @PostMapping("/logout")
    public CommonResult<?> logout(@RequestBody TokenResponse token){

        redisTemplate.delete(token.getAccessToken());
        redisTemplate.delete(token.getRefreshToken());

        return CommonResult.success("退出成功");
    }

    @PostMapping("/login")
    public CommonResult<TokenResponse> login(@RequestBody User user) {

        String username = user.getUsername();
        String password = user.getPassword();

        User user_login = userService.login(username, password);

        if (user_login == null) {
            return CommonResult.error(400, "用户名密码错误~");
        } else {
            // 生成访问令牌和刷新令牌
            Long userId = user_login.getUserId();
            String accessToken = jwtTokenUtil.generateAccessToken(userId);
            String refreshToken = jwtTokenUtil.generateRefreshToken(userId);

            redisTemplate.opsForValue().set(accessToken,userId,accessTokenExpiration, TimeUnit.SECONDS);
            redisTemplate.opsForValue().set(refreshToken,userId,refreshTokenExpiration, TimeUnit.SECONDS);

            TokenResponse token_resp = new TokenResponse(accessToken, refreshToken);
            return CommonResult.success(token_resp);
        }
    }

    @GetMapping("/getInfo")
    public CommonResult<UserDto> getInfo() {
        String token = request.getHeader("Authorization").substring(7);

        Long userId = jwtTokenUtil.getUserIdFromToken(token);
        UserDto userDto = userService.getByIdWithRoles(userId);

        if (userDto == null) {
            return CommonResult.error(400, "找不到该用户");
        } else {
            return CommonResult.success(userDto);
        }
    }

    @PostMapping("addUser")
    public CommonResult<?> addUser(@RequestBody UserDto userDto) {

        userService.saveWithRoles(userDto);

        return CommonResult.success("success");
    }

    @GetMapping("list")
    public CommonResult<List<UserDto>> getUserList() {

        List<UserDto> userDtos = userService.listUserDto();

        return CommonResult.success(userDtos);
    }

    @DeleteMapping("/{id}")
    public CommonResult<?> deleteById(@PathVariable Long id) {

        userService.deleteWithRoles(id);
        return CommonResult.success("success");
    }

    @GetMapping("/{userId}")
    public CommonResult<UserDto> getById(@PathVariable Long userId) {

        UserDto userDto = userService.getByIdWithRoles(userId);
        return CommonResult.success(userDto);
    }

    @PutMapping("updateUser")
    public CommonResult<?> updateUser(@RequestBody UserDto userDto) {
        userService.updateWithRoles(userDto);
        return CommonResult.success("success");
    }

    // 修改用户基本信息
    @PutMapping("update")
    public CommonResult<String> update(@RequestBody User user) {
        User oldUser = userService.getById(user.getUserId());
        User user1 = userService.selectByPhone(user.getPhone());
        User user2 = userService.selectByUsername(user.getUsername());
        if(!oldUser.getPhone().equals(user.getPhone()) && user1 != null) {
            return CommonResult.success("手机号已存在");
        }
        else if(!oldUser.getUsername().equals(user.getUsername()) && user2 != null) {
            return CommonResult.success("username已存在");
        }
        boolean updateSuccess = userService.updateById(user);
        if(!updateSuccess) {
            return CommonResult.success("修改失败");
        }
        return CommonResult.success("success");
    }
    // 根据用户名查询
    @PostMapping("/getByUsername")
    public boolean getByUsername(@RequestBody User user) {
        log.info("username 123 : {}", user.getUsername());
        User queryUser = userService.selectByUsername(user.getUsername());
        return queryUser == null;
    }


    // 根据电话号码查询
    @RequestMapping("/getByPhone")
    public boolean getByPhone(@RequestBody User user) {
        User queryUser = userService.selectByPhone(user.getPhone());
        return queryUser == null;
    }

    // 用户注册
    @PostMapping("/register")
    public boolean register(@RequestBody User user) {

        boolean save = userService.save(user);

        UserRole userRole = new UserRole();
        userRole.setUserId(user.getUserId());
        userRole.setRoleId(1746928701089419265L);
        userRoleService.save(userRole);
        return save;
    }
}
